package com.ed.service.impl;

import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import com.ed.context.UserContext;
import com.ed.domain.Faq;
import com.ed.domain.Option;
import com.ed.dto.AnswerQDTO;
import com.ed.dto.PageQueryDto;
import com.ed.dto.SubmitDto;
import com.ed.exception.BaseException;
import com.ed.mapper.IFaqQuestionMapper;
import com.ed.result.PageResult;
import com.ed.service.IFaqQuestionService;
import com.ed.task.AnswerQuesTask;
import com.ed.vo.QuesVO;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.scheduling.annotation.Scheduled;
import org.springframework.stereotype.Service;

import java.util.List;

@Service
@Slf4j
public class FaqQuestionServiceImpl extends ServiceImpl<IFaqQuestionMapper, Faq> implements IFaqQuestionService {
	
	@Autowired
	private IFaqQuestionMapper faqOptionMapper;
	@Autowired
	private AnswerQuesTask answerQuesTask;
	
	@Override
	public void AddFaq(Faq faq) {
		save(faq);
		
	}
	
	@Override
	public void DeleteFaq(Integer id) {
		removeById(id);
	}
	
	@Override
	public void UpdateFaq(Faq faq) {
		updateById(faq);
	}
	
	@Override
	public QuesVO getFaq(Integer id) {
		Faq faq = getById(id);
		if (faq != null) {
			QuesVO quesVO = new QuesVO();
			quesVO.setType(faq.getType());
			quesVO.setQuestion(faq.getTitle());
			return quesVO;
		}
		return null;
	}
	
	@Override
	public List<QuesVO> getFaqs() {
		List<QuesVO> quesVOS = faqOptionMapper.getFaqs();
		return quesVOS;
	}
	
	@Override
	public PageResult PageQuery(PageQueryDto pageQueryDto) {
		Page<Faq> page = baseMapper.selectPage(
			new Page<>(pageQueryDto.getPageNo(), pageQueryDto.getPageSize()),
			null
		);
		
		PageResult pageResult = new PageResult();
		pageResult.setTotal(page.getTotal());
		pageResult.setRecords(page.getRecords());
		return pageResult;
	}
	
	public static final String FAQ_CALCULATESCORE = "faq_calculateScore_";
	
	@Override
	public Integer calculateScore(SubmitDto submitDto) {
		List<AnswerQDTO> answerQDTOS = submitDto.getAnswerQDTOS();
		String idempotentKey = FAQ_CALCULATESCORE + UserContext.getCurrentUser();
		//检查是否为重复提交
		checkAndRecordIdempotent(idempotentKey);
		Integer score = 0;
		for (AnswerQDTO answerQDTO : answerQDTOS) {
			if (answerQDTO.getOptionIndex() != null) {
				Integer index = answerQDTO.getOptionIndex();
				Option option = answerQDTO.getOption().get(index);
				score += option.getWeight();
			}
		}
		answerQuesTask.record(answerQDTOS, score, UserContext.getCurrentUser(),submitDto.getStartTime());
		return score;
	}
	
	/**
	 * 检查当前请求是否重复提交
	 *
	 * @param IdempotentKey
	 */
	public void checkAndRecordIdempotent(String IdempotentKey) {
		// 使用 compute 原子性地更新或插入时间戳
		Long result = IdempotentMap.compute(IdempotentKey, (key, oldTime) -> {
			long currentTime = System.currentTimeMillis();
			if (oldTime != null) {
				// 计算时间差（毫秒）
				long timeDifferenceInMillis = currentTime - oldTime;
				// 若5秒内重复请求，设置结果为 -1
				if (timeDifferenceInMillis <= 5 * 1000) {
					return -1L;
				}
			}
			// 如果 oldTime 为 null 或时间差超过5秒，更新时间戳为当前时间
			return currentTime;
		});
		// 检查 compute 的结果，如果 result 是 -1，进行拦截
		if (result == -1L) {
			throw new BaseException("请勿重复提交");
		}
	}
	
	/**
	 * 每 10 分钟执行一次清理任务
	 */
	@Scheduled(fixedRate = 10 * 60 * 1000) // 10分钟
	public void cleanupExpiredEntries() {
		log.info("执行幂等 map 清理");
		//早于该时间戳的都是过期记录
		long cutoffTime = System.currentTimeMillis() - 5000L;
		IdempotentMap.entrySet().removeIf(entry -> entry.getValue() <= cutoffTime);
	}
}
